/*************************************/
/*	PROGRAMA SERVIDOR DE TIPO    */
/*	TELNET CON SOLO 2 COMANDOS   */
/*************************************/

//Version no operativa del servidor.
//Me he echo un lio, con todo esto. empezar de 0, en la proxima revision.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netbd.h>
#include <netinet/in.h>

#define TPORT 10000 	//PUERTO TCP
#define TAM 256		//TAMAÑO DE LOS DATOS
#define PATH "/usr/bin/" //PATH DE BINARIOS DEL SISTEMA

void procmsg(char *msg); //Procesar un mensaje.
void extComando(char *msg, char *comando, int longmsg); //Extraer un comando del msg y ponerlo en comando

int main(int argc, char **argv)
{
  int ssd, csd, fd;	//Servidor socket descriptor, Cliente socket descriptor, y descriptor de ficheros para los temporales
  int slong, clong;//longitud servidor, longitud cliente para las estructuras sockaddr
  int subproceso; //Utilizado para poder crear subprocesos.
  int bytesLeidos, bytesEnviados; //Utilizarlo para saber cuantos bytes se han leido del socket
  char rdatos[TAM], edatos[TAM];	//Recibir datos y enviar datos.
  struct sockaddr servidor, cliente; //Datos del servidor y los clientes.
  
  //CREAMOS EL SOCKET DEL SERVIDOR
  if((ssd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  {
    perror("No se pudo crear el socket.\n");
    return -1;
  }
  
  //Rellenamos la estructura del servidor, con los datos del mismo.
  
  ssd.sin_family = AF_INET;
  ssd.sin_port = htons(TPORT);
  ssd.sin_addr = htonl(INADDR_ANY);	//La direccion ip actual.
  memset(&(ssd.sin_zero), '\0', 8); //Rellenamos a 0, para equiparar con la estructura sockaddr
  
  //Bindeamos el socket al puerto.
  if (bind(ssd, (struct sockaddr*)&servidor, sizeof(sockaddr)) == -1)
  {
    perror("No se pudo reservar el puerto.\n");
    return -1;
  }
  
  //servidor a la escucha
  if (listen(ssd, 5) == -1)
  {
    perror("El servidor no se ha puesto a la escucha.\n");
    return -1;
  }
  
  //Bucle infinito que acepta conexiones.
  
  while(1)
  {
    if((csd = accept(ssd, (struct sockaddr*)&cliente, sizeof(struct cliente))) == -1)
    {
      perror("Error conectando con uno de los clientes.\n");
    }
    
    subproceso = fork();
    if( subproceso == 0)//Codigo del proceso hijo.
    {
      //close(ssd);	//El hijo, no necesita el socket del proceso padre para atender la peticion
      if((bytesLeidos = recv(ssd, rdatos, TAM)) ==  -1)
      {
      	printf("Error recibiendo datos del cliente\n");
      }
      else
      {
		procmsg(&rdatos);
		send(csd, rdatos, sizeof(rdatos));
	  }
    }
    else if(subproceso > 0)//Codigo del proceso padre, para atender a la peticion.
    {
    	close(csd);	//libera el socket del cliente, dado que el proceso padre no lo necesita y debe poder aceptar mas conexiones.
    }
    else
    {
      printf("Error creando el proceso hijo, para tender peticion del cliente");
    }
  }
}

//funcion que procesa los mensajes recividos del cliente.
void procmsg(char *msg)
{
  //Se lee la longitud del mensaje.
  int longmsg = atoi(msg[0]);
  char comando[254];
  struct tm *tmPtr;
  time_t tiempo;
  
  extComando(&msg, &comando, longmsg);	//extraemos el comando
  
  
  switch(atoi(msg[1])) //miramos el tipo de mensaje.
  {
    case 	0 :

      if(strcmp(comando, "fecha") == 0)
      {
		edatos[0]=20;
		edatos[1]=1;
		time(&tiempo);
		tmPtr = localtime(&tiempo);
		strftime(&edatos[2], 20,"%d/%m/%y", tmPtr);
		edatos[23] = 1;
      }
      else if(strcmp(comando, "usuarios") == 0)
      {
          if(system("who > /home/tnt.tmp"))
          {
              if(fd = open("/home/tnt.tmp", O_RDONLY, 0644) == -1 )
              {
                  perror("Error, abriendo fichero temporal de comando: \n");
              }
              else
              {
                  while( (bytesLeidos = read(fd, edatos, TAM)) > 0)
                  {
                      send(csd, edatos, sizeof(edatos),0);
                  }
              }

          }
      }
      else if(strcmp(comando, "salir") == 0)
      {
      }
      else
      {
			//Enviar comando incorrecto
      }
      break;
    case	1:
        break;
  }
}

void extComando(char *msg, char *comando, int longmsg)	//Cadena de donde se extraera, cadena donde se almacenara el comando y longitud del comando
{
  int i, c =0;	//i para el bucle y el array del msg, c para el array de comandos
  
  for (i=2; i<= (longmsg+2); i++)	//Se le suma 2 a longmsg, porque el comando empieza en el elemento 2, si no lo sumaramos, no cogeria el comando completo.
  {
    comando[c] = msg[i];
  }
}
  
    